<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <!-- 页面点击小红心 -->
  <script type="text/javascript" src="/js/clicklove.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.js"></script> 

  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.1.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/blog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/blog/css/main.css">


<link rel="stylesheet" href="/blog/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"linzhuangrong.gitee.io","root":"/blog/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="Redis支持三种集群方案">
<meta property="og:type" content="article">
<meta property="og:title" content="Redis支持三种集群方案">
<meta property="og:url" content="https://linzhuangrong.gitee.io/blog/2019/09/15/redis-cluster5%20-%202/index.html">
<meta property="og:site_name" content="Rong的博客">
<meta property="og:description" content="Redis支持三种集群方案">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://oscimg.oschina.net/oscnet/632381-20200316092434553-1122086987.png">
<meta property="og:image" content="https://oscimg.oschina.net/oscnet/632381-20200316092434904-227928571.png">
<meta property="og:image" content="https://oscimg.oschina.net/oscnet/632381-20200316092435147-202966399.png">
<meta property="og:image" content="https://oscimg.oschina.net/oscnet/632381-20200316092435392-508884462.png">
<meta property="og:image" content="https://oscimg.oschina.net/oscnet/632381-20200316092435631-1120920134.png">
<meta property="article:published_time" content="2019-09-14T16:00:00.000Z">
<meta property="article:modified_time" content="2020-08-31T15:56:23.971Z">
<meta property="article:author" content="林壮荣">
<meta property="article:tag" content="Redis">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://oscimg.oschina.net/oscnet/632381-20200316092434553-1122086987.png">

<link rel="canonical" href="https://linzhuangrong.gitee.io/blog/2019/09/15/redis-cluster5%20-%202/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>Redis支持三种集群方案 | Rong的博客</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/blog/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Rong的博客</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/blog/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/blog/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/blog/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://linzhuangrong.gitee.io/blog/2019/09/15/redis-cluster5%20-%202/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/blog/images/avatar.gif">
      <meta itemprop="name" content="林壮荣">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Rong的博客">
    </span>
      <header class="post-header">
	  
        <h1 class="post-title" itemprop="name headline">
          Redis支持三种集群方案
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-09-15 00:00:00" itemprop="dateCreated datePublished" datetime="2019-09-15T00:00:00+08:00">2019-09-15</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-08-31 23:56:23" itemprop="dateModified" datetime="2020-08-31T23:56:23+08:00">2020-08-31</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/%E9%9B%86%E7%BE%A4%E6%9C%8D%E5%8A%A1/" itemprop="url" rel="index"><span itemprop="name">集群服务</span></a>
                </span>
                  ，
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/%E9%9B%86%E7%BE%A4%E6%9C%8D%E5%8A%A1/Redis/" itemprop="url" rel="index"><span itemprop="name">Redis</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span>
            <div class="post-description">Redis支持三种集群方案</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一文掌握Redis的三种集群方案"><a href="#一文掌握Redis的三种集群方案" class="headerlink" title="一文掌握Redis的三种集群方案"></a><a target="_blank" rel="noopener" href="https://www.cnblogs.com/spec-dog/p/12501895.html">一文掌握Redis的三种集群方案</a></h1><p>在开发测试环境中，我们一般搭建Redis的单实例来应对开发测试需求，但是在生产环境，如果对可用性、可靠性要求较高，则需要引入Redis的集群方案。虽然现在各大云平台有提供缓存服务可以直接使用，但了解一下其背后的实现与原理总还是有些必要（比如面试）， 本文就一起来学习一下Redis的几种集群方案。</p>
<p>Redis支持三种集群方案</p>
<ul>
<li>主从复制模式</li>
<li>Sentinel（哨兵）模式</li>
<li>Cluster模式</li>
</ul>
<h2 id="主从复制模式"><a href="#主从复制模式" class="headerlink" title="主从复制模式"></a>主从复制模式</h2><h3 id="1-基本原理"><a href="#1-基本原理" class="headerlink" title="1. 基本原理"></a>1. 基本原理</h3><p>主从复制模式中包含一个主数据库实例（master）与一个或多个从数据库实例（slave），如下图</p>
<p><img src="https://oscimg.oschina.net/oscnet/632381-20200316092434553-1122086987.png" alt="redis-master-slave"></p>
<p>客户端可对主数据库进行读写操作，对从数据库进行读操作，主数据库写入的数据会实时自动同步给从数据库。</p>
<p>具体工作机制为：</p>
<ol>
<li>slave启动后，向master发送SYNC命令，master接收到SYNC命令后通过bgsave保存快照（即上文所介绍的RDB持久化），并使用缓冲区记录保存快照这段时间内执行的写命令</li>
<li>master将保存的快照文件发送给slave，并继续记录执行的写命令</li>
<li>slave接收到快照文件后，加载快照文件，载入数据</li>
<li>master快照发送完后开始向slave发送缓冲区的写命令，slave接收命令并执行，完成复制初始化</li>
<li>此后master每次执行一个写命令都会同步发送给slave，保持master与slave之间数据的一致性</li>
</ol>
<h3 id="2-部署示例"><a href="#2-部署示例" class="headerlink" title="2. 部署示例"></a>2. 部署示例</h3><p>本示例基于Redis 5.0.3版。</p>
<p>redis.conf的主要配置</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">###网络相关###</span><br><span class="line"># bind 127.0.0.1 # 绑定监听的网卡IP，注释掉或配置成0.0.0.0可使任意IP均可访问</span><br><span class="line">protected-mode no # 关闭保护模式，使用密码访问</span><br><span class="line">port 6379  # 设置监听端口，建议生产环境均使用自定义端口</span><br><span class="line">timeout 30 # 客户端连接空闲多久后断开连接，单位秒，0表示禁用</span><br><span class="line"></span><br><span class="line">###通用配置###</span><br><span class="line">daemonize yes # 在后台运行</span><br><span class="line">pidfile &#x2F;var&#x2F;run&#x2F;redis_6379.pid  # pid进程文件名</span><br><span class="line">logfile &#x2F;usr&#x2F;local&#x2F;redis&#x2F;logs&#x2F;redis.log # 日志文件的位置</span><br><span class="line"></span><br><span class="line">###RDB持久化配置###</span><br><span class="line">save 900 1 # 900s内至少一次写操作则执行bgsave进行RDB持久化</span><br><span class="line">save 300 10</span><br><span class="line">save 60 10000 </span><br><span class="line"># 如果禁用RDB持久化，可在这里添加 save &quot;&quot;</span><br><span class="line">rdbcompression yes #是否对RDB文件进行压缩，建议设置为no，以（磁盘）空间换（CPU）时间</span><br><span class="line">dbfilename dump.rdb # RDB文件名称</span><br><span class="line">dir &#x2F;usr&#x2F;local&#x2F;redis&#x2F;datas # RDB文件保存路径，AOF文件也保存在这里</span><br><span class="line"></span><br><span class="line">###AOF配置###</span><br><span class="line">appendonly yes # 默认值是no，表示不使用AOF增量持久化的方式，使用RDB全量持久化的方式</span><br><span class="line">appendfsync everysec # 可选值 always， everysec，no，建议设置为everysec</span><br><span class="line"></span><br><span class="line">###设置密码###</span><br><span class="line">requirepass 123456 # 设置复杂一点的密码</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>部署主从复制模式只需稍微调整slave的配置，在redis.conf中添加</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">replicaof 127.0.0.1 6379 # master的ip，port</span><br><span class="line">masterauth 123456 # master的密码</span><br><span class="line">replica-serve-stale-data no # 如果slave无法与master同步，设置成slave不可读，方便监控脚本发现问题</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>本示例在单台服务器上配置master端口6379，两个slave端口分别为7001,7002，启动master，再启动两个slave</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[root@dev-server-1 master-slave]# redis-server master.conf</span><br><span class="line">[root@dev-server-1 master-slave]# redis-server slave1.conf</span><br><span class="line">[root@dev-server-1 master-slave]# redis-server slave2.conf</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>进入master数据库，写入一个数据，再进入一个slave数据库，立即便可访问刚才写入master数据库的数据。如下所示</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">[root@dev-server-1 master-slave]# redis-cli </span><br><span class="line">127.0.0.1:6379&gt; auth 123456</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; set site blog.jboost.cn</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; get site</span><br><span class="line">&quot;blog.jboost.cn&quot;</span><br><span class="line">127.0.0.1:6379&gt; info replication</span><br><span class="line"><span class="meta">#</span><span class="bash"> Replication</span></span><br><span class="line">role:master</span><br><span class="line">connected_slaves:2</span><br><span class="line">slave0:ip=127.0.0.1,port=7001,state=online,offset=13364738,lag=1</span><br><span class="line">slave1:ip=127.0.0.1,port=7002,state=online,offset=13364738,lag=0</span><br><span class="line">...</span><br><span class="line">127.0.0.1:6379&gt; exit</span><br><span class="line"></span><br><span class="line">[root@dev-server-1 master-slave]# redis-cli -p 7001</span><br><span class="line">127.0.0.1:7001&gt; auth 123456</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:7001&gt; get site</span><br><span class="line">&quot;blog.jboost.cn&quot;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>执行<code>info replication</code>命令可以查看连接该数据库的其它库的信息，如上可看到有两个slave连接到master</p>
<h3 id="3-主从复制的优缺点"><a href="#3-主从复制的优缺点" class="headerlink" title="3. 主从复制的优缺点"></a>3. 主从复制的优缺点</h3><p>优点：</p>
<ol>
<li>master能自动将数据同步到slave，可以进行读写分离，分担master的读压力</li>
<li>master、slave之间的同步是以非阻塞的方式进行的，同步期间，客户端仍然可以提交查询或更新请求</li>
</ol>
<p>缺点：</p>
<ol>
<li>不具备自动容错与恢复功能，master或slave的宕机都可能导致客户端请求失败，需要等待机器重启或手动切换客户端IP才能恢复</li>
<li>master宕机，如果宕机前数据没有同步完，则切换IP后会存在数据不一致的问题</li>
<li>难以支持在线扩容，Redis的容量受限于单机配置</li>
</ol>
<h2 id="Sentinel（哨兵）模式"><a href="#Sentinel（哨兵）模式" class="headerlink" title="Sentinel（哨兵）模式"></a>Sentinel（哨兵）模式</h2><h3 id="1-基本原理-1"><a href="#1-基本原理-1" class="headerlink" title="1. 基本原理"></a>1. 基本原理</h3><p>哨兵模式基于主从复制模式，只是引入了哨兵来监控与自动处理故障。如图</p>
<p><img src="https://oscimg.oschina.net/oscnet/632381-20200316092434904-227928571.png" alt="redis-sentinel"></p>
<p>哨兵顾名思义，就是来为Redis集群站哨的，一旦发现问题能做出相应的应对处理。其功能包括</p>
<ol>
<li>监控master、slave是否正常运行</li>
<li>当master出现故障时，能自动将一个slave转换为master（大哥挂了，选一个小弟上位）</li>
<li>多个哨兵可以监控同一个Redis，哨兵之间也会自动监控</li>
</ol>
<p>哨兵模式的具体工作机制：</p>
<p>在配置文件中通过<code>sentinel monitor &lt;master-name&gt; &lt;ip&gt; &lt;redis-port&gt; &lt;quorum&gt;</code>来定位master的IP、端口，一个哨兵可以监控多个master数据库，只需要提供多个该配置项即可。哨兵启动后，会与要监控的master建立两条连接：</p>
<ol>
<li>一条连接用来订阅master的<code>_sentinel_:hello</code>频道与获取其他监控该master的哨兵节点信息</li>
<li>另一条连接定期向master发送INFO等命令获取master本身的信息</li>
</ol>
<p>与master建立连接后，哨兵会执行三个操作：</p>
<ol>
<li>定期（一般10s一次，当master被标记为主观下线时，改为1s一次）向master和slave发送INFO命令</li>
<li>定期向master和slave的<code>_sentinel_:hello</code>频道发送自己的信息</li>
<li>定期（1s一次）向master、slave和其他哨兵发送PING命令</li>
</ol>
<p>发送INFO命令可以获取当前数据库的相关信息从而实现新节点的自动发现。所以说哨兵只需要配置master数据库信息就可以自动发现其slave信息。获取到slave信息后，哨兵也会与slave建立两条连接执行监控。通过INFO命令，哨兵可以获取主从数据库的最新信息，并进行相应的操作，比如角色变更等。</p>
<p>接下来哨兵向主从数据库的_sentinel_:hello频道发送信息与同样监控这些数据库的哨兵共享自己的信息，发送内容为哨兵的ip端口、运行id、配置版本、master名字、master的ip端口还有master的配置版本。这些信息有以下用处：</p>
<ol>
<li>其他哨兵可以通过该信息判断发送者是否是新发现的哨兵，如果是的话会创建一个到该哨兵的连接用于发送PING命令。</li>
<li>其他哨兵通过该信息可以判断master的版本，如果该版本高于直接记录的版本，将会更新</li>
<li>当实现了自动发现slave和其他哨兵节点后，哨兵就可以通过定期发送PING命令定时监控这些数据库和节点有没有停止服务。</li>
</ol>
<p>如果被PING的数据库或者节点超时（通过<code>sentinel down-after-milliseconds master-name milliseconds</code>配置）未回复，哨兵认为其主观下线（sdown，s就是Subjectively —— 主观地）。如果下线的是master，哨兵会向其它哨兵发送命令询问它们是否也认为该master主观下线，如果达到一定数目（即配置文件中的quorum）投票，哨兵会认为该master已经客观下线（odown，o就是Objectively —— 客观地），并选举领头的哨兵节点对主从系统发起故障恢复。若没有足够的sentinel进程同意master下线，master的客观下线状态会被移除，若master重新向sentinel进程发送的PING命令返回有效回复，master的主观下线状态就会被移除</p>
<p>哨兵认为master客观下线后，故障恢复的操作需要由选举的领头哨兵来执行，选举采用Raft算法：</p>
<ol>
<li>发现master下线的哨兵节点（我们称他为A）向每个哨兵发送命令，要求对方选自己为领头哨兵</li>
<li>如果目标哨兵节点没有选过其他人，则会同意选举A为领头哨兵</li>
<li>如果有超过一半的哨兵同意选举A为领头，则A当选</li>
<li>如果有多个哨兵节点同时参选领头，此时有可能存在一轮投票无竞选者胜出，此时每个参选的节点等待一个随机时间后再次发起参选请求，进行下一轮投票竞选，直至选举出领头哨兵</li>
</ol>
<p>选出领头哨兵后，领头者开始对系统进行故障恢复，从出现故障的master的从数据库中挑选一个来当选新的master,选择规则如下：</p>
<ol>
<li>所有在线的slave中选择优先级最高的，优先级可以通过slave-priority配置</li>
<li>如果有多个最高优先级的slave，则选取复制偏移量最大（即复制越完整）的当选</li>
<li>如果以上条件都一样，选取id最小的slave</li>
</ol>
<p>挑选出需要继任的slave后，领头哨兵向该数据库发送命令使其升格为master，然后再向其他slave发送命令接受新的master，最后更新数据。将已经停止的旧的master更新为新的master的从数据库，使其恢复服务后以slave的身份继续运行。</p>
<h3 id="2-部署演示"><a href="#2-部署演示" class="headerlink" title="2. 部署演示"></a>2. 部署演示</h3><p>本示例基于Redis 5.0.3版。</p>
<p>哨兵模式基于前文的主从复制模式。哨兵的配置文件为sentinel.conf，在文件中添加</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">sentinel monitor mymaster 127.0.0.1 6379 1 # mymaster定义一个master数据库的名称，后面是master的ip， port，1表示至少需要一个Sentinel进程同意才能将master判断为失效，如果不满足这个条件，则自动故障转移（failover）不会执行</span><br><span class="line">sentinel auth-pass mymaster 123456 # master的密码</span><br><span class="line"></span><br><span class="line">sentinel down-after-milliseconds mymaster 5000 # 5s未回复PING，则认为master主观下线，默认为30s</span><br><span class="line">sentinel parallel-syncs mymaster 2  # 指定在执行故障转移时，最多可以有多少个slave实例在同步新的master实例，在slave实例较多的情况下这个数字越小，同步的时间越长，完成故障转移所需的时间就越长</span><br><span class="line">sentinel failover-timeout mymaster 300000 # 如果在该时间（ms）内未能完成故障转移操作，则认为故障转移失败，生产环境需要根据数据量设置该值</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<blockquote>
<p>一个哨兵可以监控多个master数据库，只需按上述配置添加多套</p>
</blockquote>
<p>分别以26379,36379,46379端口启动三个sentinel</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[root@dev-server-1 sentinel]# redis-server sentinel1.conf --sentinel</span><br><span class="line">[root@dev-server-1 sentinel]# redis-server sentinel2.conf --sentinel</span><br><span class="line">[root@dev-server-1 sentinel]# redis-server sentinel3.conf --sentinel</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>也可以使用<code>redis-sentinel sentinel1.conf</code>命令启动。此时集群包含一个master、两个slave、三个sentinel，如图，</p>
<p><img src="https://oscimg.oschina.net/oscnet/632381-20200316092435147-202966399.png" alt="redis-cluster-instance"></p>
<p>我们来模拟master挂掉的场景，执行<code>kill -9 3017</code>将master进程干掉，进入slave中执行<code>info replication</code>查看，</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">[root@dev-server-1 sentinel]# redis-cli -p 7001</span><br><span class="line">127.0.0.1:7001&gt; auth 123456</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:7001&gt; info replication</span><br><span class="line"><span class="meta">#</span><span class="bash"> Replication</span></span><br><span class="line">role:slave</span><br><span class="line">master_host:127.0.0.1</span><br><span class="line">master_port:7002</span><br><span class="line">master_link_status:up</span><br><span class="line">master_last_io_seconds_ago:1</span><br><span class="line">master_sync_in_progress:0</span><br><span class="line"><span class="meta">#</span><span class="bash"> 省略</span></span><br><span class="line">127.0.0.1:7001&gt; exit</span><br><span class="line">[root@dev-server-1 sentinel]# redis-cli -p 7002</span><br><span class="line">127.0.0.1:7002&gt; auth 123456</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:7002&gt; info replication</span><br><span class="line"><span class="meta">#</span><span class="bash"> Replication</span></span><br><span class="line">role:master</span><br><span class="line">connected_slaves:1</span><br><span class="line">slave0:ip=127.0.0.1,port=7001,state=online,offset=13642721,lag=1</span><br><span class="line"><span class="meta">#</span><span class="bash"> 省略</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>可以看到slave 7002已经成功上位晋升为master（role：master），接收一个slave 7001的连接。此时查看slave2.conf配置文件，发现<code>replicaof</code>的配置已经被移除了，slave1.conf的配置文件里<code>replicaof 127.0.0.1 6379</code>被改为<code>replicaof 127.0.0.1 7002</code>。重新启动master，也可以看到master.conf配置文件中添加了<code>replicaof 127.0.0.1 7002</code>的配置项，可见大哥（master）下位后，再出来混就只能当当小弟（slave）了，三十年河东三十年河西。</p>
<h3 id="3-哨兵模式的优缺点"><a href="#3-哨兵模式的优缺点" class="headerlink" title="3. 哨兵模式的优缺点"></a>3. 哨兵模式的优缺点</h3><p>优点：</p>
<ol>
<li>哨兵模式基于主从复制模式，所以主从复制模式有的优点，哨兵模式也有</li>
<li>哨兵模式下，master挂掉可以自动进行切换，系统可用性更高</li>
</ol>
<p>缺点：</p>
<ol>
<li>同样也继承了主从模式难以在线扩容的缺点，Redis的容量受限于单机配置</li>
<li>需要额外的资源来启动sentinel进程，实现相对复杂一点，同时slave节点作为备份节点不提供服务</li>
</ol>
<h2 id="Cluster模式"><a href="#Cluster模式" class="headerlink" title="Cluster模式"></a>Cluster模式</h2><h3 id="1-基本原理-2"><a href="#1-基本原理-2" class="headerlink" title="1. 基本原理"></a>1. 基本原理</h3><p>哨兵模式解决了主从复制不能自动故障转移，达不到高可用的问题，但还是存在难以在线扩容，Redis容量受限于单机配置的问题。Cluster模式实现了Redis的分布式存储，即每台节点存储不同的内容，来解决在线扩容的问题。如图</p>
<p><img src="https://oscimg.oschina.net/oscnet/632381-20200316092435392-508884462.png" alt="redis-cluster"></p>
<p>Cluster采用无中心结构,它的特点如下：</p>
<ol>
<li>所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽</li>
<li>节点的fail是通过集群中超过半数的节点检测失效时才生效</li>
<li>客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可</li>
</ol>
<p>Cluster模式的具体工作机制：</p>
<ol>
<li>在Redis的每个节点上，都有一个插槽（slot），取值范围为0-16383</li>
<li>当我们存取key的时候，Redis会根据CRC16的算法得出一个结果，然后把结果对16384求余数，这样每个key都会对应一个编号在0-16383之间的哈希槽，通过这个值，去找到对应的插槽所对应的节点，然后直接自动跳转到这个对应的节点上进行存取操作</li>
<li>为了保证高可用，Cluster模式也引入主从复制模式，一个主节点对应一个或者多个从节点，当主节点宕机的时候，就会启用从节点</li>
<li>当其它主节点ping一个主节点A时，如果半数以上的主节点与A通信超时，那么认为主节点A宕机了。如果主节点A和它的从节点都宕机了，那么该集群就无法再提供服务了</li>
</ol>
<p>Cluster模式集群节点最小配置6个节点(3主3从，因为需要半数以上)，其中主节点提供读写操作，从节点作为备用节点，不提供请求，只作为故障转移使用。</p>
<h3 id="2-部署演示-1"><a href="#2-部署演示-1" class="headerlink" title="2. 部署演示"></a>2. 部署演示</h3><p>本示例基于Redis 5.0.3版。</p>
<p>Cluster模式的部署比较简单，首先在redis.conf中</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">port 7100 # 本示例6个节点端口分别为7100,7200,7300,7400,7500,7600 </span><br><span class="line">daemonize yes # r后台运行 </span><br><span class="line">pidfile &#x2F;var&#x2F;run&#x2F;redis_7100.pid # pidfile文件对应7100,7200,7300,7400,7500,7600 </span><br><span class="line">cluster-enabled yes # 开启集群模式 </span><br><span class="line">masterauth passw0rd # 如果设置了密码，需要指定master密码</span><br><span class="line">cluster-config-file nodes_7100.conf # 集群的配置文件，同样对应7100,7200等六个节点</span><br><span class="line">cluster-node-timeout 15000 # 请求超时 默认15秒，可自行设置 </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>分别以端口7100,7200,7300,7400,7500,7600 启动六个实例(如果是每个服务器一个实例则配置可一样)</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[root@dev-server-1 cluster]# redis-server redis_7100.conf</span><br><span class="line">[root@dev-server-1 cluster]# redis-server redis_7200.conf</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>然后通过命令将这个6个实例组成一个3主节点3从节点的集群，</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7100 127.0.0.1:7200 127.0.0.1:7300 127.0.0.1:7400 127.0.0.1:7500 127.0.0.1:7600 -a passw0rd</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>执行结果如图</p>
<p><img src="https://oscimg.oschina.net/oscnet/632381-20200316092435631-1120920134.png" alt="redis-cluster-deploy"></p>
<p>可以看到 7100， 7200， 7300 作为3个主节点，分配的slot分别为 0-5460， 5461-10922， 10923-16383， 7600作为7100的slave， 7500作为7300的slave，7400作为7200的slave。</p>
<p>我们连接7100设置一个值</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">[root@dev-server-1 cluster]# redis-cli -p 7100 -c -a passw0rd</span><br><span class="line">Warning: Using a password with &#x27;-a&#x27; or &#x27;-u&#x27; option on the command line interface may not be safe.</span><br><span class="line">127.0.0.1:7100&gt; set site blog.jboost.cn</span><br><span class="line"><span class="meta">-&gt;</span><span class="bash"> Redirected to slot [9421] located at 127.0.0.1:7200</span></span><br><span class="line">OK</span><br><span class="line">127.0.0.1:7200&gt; get site</span><br><span class="line">&quot;blog.jboost.cn&quot;</span><br><span class="line">127.0.0.1:7200&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>注意添加 -c 参数表示以集群模式，否则报<code>(error) MOVED 9421 127.0.0.1:7200</code>错误， 以 -a 参数指定密码，否则报<code>(error) NOAUTH Authentication required</code>错误。</p>
<p>从上面命令看到key为site算出的slot为9421，落在7200节点上，所以有<code>Redirected to slot [9421] located at 127.0.0.1:7200</code>，集群会自动进行跳转。因此客户端可以连接任何一个节点来进行数据的存取。</p>
<p>通过<code>cluster nodes</code>可查看集群的节点信息</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:7200&gt; cluster nodes</span><br><span class="line">eb28aaf090ed1b6b05033335e3d90a202b422d6c 127.0.0.1:7500@17500 slave c1047de2a1b5d5fa4666d554376ca8960895a955 0 1584165266071 5 connected</span><br><span class="line">4cc0463878ae00e5dcf0b36c4345182e021932bc 127.0.0.1:7400@17400 slave 5544aa5ff20f14c4c3665476de6e537d76316b4a 0 1584165267074 4 connected</span><br><span class="line">dbbb6420d64db22f35a9b6fa460b0878c172a2fb 127.0.0.1:7100@17100 master - 0 1584165266000 1 connected 0-5460</span><br><span class="line">d4b434f5829e73e7e779147e905eea6247ffa5a2 127.0.0.1:7600@17600 slave dbbb6420d64db22f35a9b6fa460b0878c172a2fb 0 1584165265000 6 connected</span><br><span class="line">5544aa5ff20f14c4c3665476de6e537d76316b4a 127.0.0.1:7200@17200 myself,master - 0 1584165267000 2 connected 5461-10922</span><br><span class="line">c1047de2a1b5d5fa4666d554376ca8960895a955 127.0.0.1:7300@17300 master - 0 1584165268076 3 connected 10923-16383</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>我们将7200通过<code>kill -9 pid</code>杀死进程来验证集群的高可用，重新进入集群执行<code>cluster nodes</code>可以看到7200 fail了，但是7400成了master，重新启动7200，可以看到此时7200已经变成了slave。</p>
<h3 id="3-Cluster模式的优缺点"><a href="#3-Cluster模式的优缺点" class="headerlink" title="3. Cluster模式的优缺点"></a>3. Cluster模式的优缺点</h3><p>优点：</p>
<ol>
<li>无中心架构，数据按照slot分布在多个节点。</li>
<li>集群中的每个节点都是平等的关系，每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接，而且这些连接保持活跃，这样就保证了我们只需要连接集群中的任意一个节点，就可以获取到其他节点的数据。</li>
<li>可线性扩展到1000多个节点，节点可动态添加或删除</li>
<li>能够实现自动故障转移，节点之间通过gossip协议交换状态信息，用投票机制完成slave到master的角色转换</li>
</ol>
<p>缺点：</p>
<ol>
<li>客户端实现复杂，驱动要求实现Smart Client，缓存slots mapping信息并及时更新，提高了开发难度。目前仅JedisCluster相对成熟，异常处理还不完善，比如常见的“max redirect exception”</li>
<li>节点会因为某些原因发生阻塞（阻塞时间大于 cluster-node-timeout）被判断下线，这种failover是没有必要的</li>
<li>数据通过异步复制，不保证数据的强一致性</li>
<li>slave充当“冷备”，不能缓解读压力</li>
<li>批量操作限制，目前只支持具有相同slot值的key执行批量操作，对mset、mget、sunion等操作支持不友好</li>
<li>key事务操作支持有线，只支持多key在同一节点的事务操作，多key分布不同节点时无法使用事务功能</li>
<li>不支持多数据库空间，单机redis可以支持16个db，集群模式下只能使用一个，即db 0</li>
</ol>
<p>Redis Cluster模式不建议使用pipeline和multi-keys操作，减少max redirect产生的场景。</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>本文介绍了Redis集群方案的三种模式，其中主从复制模式能实现读写分离，但是不能自动故障转移；哨兵模式基于主从复制模式，能实现自动故障转移，达到高可用，但与主从复制模式一样，不能在线扩容，容量受限于单机的配置；Cluster模式通过无中心化架构，实现分布式存储，可进行线性扩展，也能高可用，但对于像批量操作、事务操作等的支持性不够好。三种模式各有优缺点，可根据实际场景进行选择。</p>
<p>参考：</p>
<ol>
<li><a target="_blank" rel="noopener" href="https://blog.csdn.net/q649381130/article/details/79931791">https://blog.csdn.net/q649381130/article/details/79931791</a></li>
<li><a target="_blank" rel="noopener" href="https://www.cnblogs.com/51life/p/10233340.html">https://www.cnblogs.com/51life/p/10233340.html</a></li>
<li><a target="_blank" rel="noopener" href="https://www.cnblogs.com/chensuqian/p/10538365.html">https://www.cnblogs.com/chensuqian/p/10538365.html</a></li>
<li><a target="_blank" rel="noopener" href="https://stor.51cto.com/art/201910/604653.htm">https://stor.51cto.com/art/201910/604653.htm</a></li>
</ol>

    </div>

    
    
    
 
    <div>
      
        
<div class="my_post_copyright">
  <script src="//cdn.bootcss.com/clipboard.js/1.5.10/clipboard.min.js"></script>
  
  <!-- JS库 sweetalert 可修改路径 -->
  <script src="https://cdn.bootcss.com/jquery/2.0.0/jquery.min.js"></script>
  <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
  <p><span>本文标题:</span><a href="/blog/2019/09/15/redis-cluster5%20-%202/">Redis支持三种集群方案</a></p>
  <p><span>文章作者:</span><a href="/" title="访问  的个人博客"></a></p>
  <p><span>发布时间:</span>2019年09月15日 - 00:09</p>
  <p><span>最后更新:</span>2020年08月31日 - 23:08</p>
  <p><span>原始链接:</span><a href="/blog/2019/09/15/redis-cluster5%20-%202/" title="Redis支持三种集群方案">https://linzhuangrong.gitee.io/blog/2019/09/15/redis-cluster5%20-%202/</a>
    <span class="copy-path"  title="点击复制文章链接"><i class="fa fa-clipboard" data-clipboard-text="https://linzhuangrong.gitee.io/blog/2019/09/15/redis-cluster5%20-%202/"  aria-label="复制成功！"></i></span>
  </p>
  <p><span>许可协议:</span><i class="fa fa-creative-commons"></i> 转载请保留原文链接及作者。</p>  
</div>
<script> 
    var clipboard = new Clipboard('.fa-clipboard');
    $(".fa-clipboard").click(function(){
      clipboard.on('success', function(){
        swal({   
          title: "",   
          text: '复制成功',
          icon: "success", 
          showConfirmButton: true
          });
    });
    });  
</script>


      
    </div>

      <footer class="post-footer">
          <div class="post-tags">
              <a href="/blog/tags/Redis/" rel="tag"># Redis</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/blog/2019/09/15/redis-cluster5%20-%203/" rel="prev" title="Redis Cluster在线迁移">
      <i class="fa fa-chevron-left"></i> Redis Cluster在线迁移
    </a></div>
      <div class="post-nav-item">
    <a href="/blog/2019/11/15/LVM/" rel="next" title="Lvm管理">
      Lvm管理 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E6%96%87%E6%8E%8C%E6%8F%A1Redis%E7%9A%84%E4%B8%89%E7%A7%8D%E9%9B%86%E7%BE%A4%E6%96%B9%E6%A1%88"><span class="nav-number">1.</span> <span class="nav-text">一文掌握Redis的三种集群方案</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.1.</span> <span class="nav-text">主从复制模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86"><span class="nav-number">1.1.1.</span> <span class="nav-text">1. 基本原理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-%E9%83%A8%E7%BD%B2%E7%A4%BA%E4%BE%8B"><span class="nav-number">1.1.2.</span> <span class="nav-text">2. 部署示例</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9"><span class="nav-number">1.1.3.</span> <span class="nav-text">3. 主从复制的优缺点</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Sentinel%EF%BC%88%E5%93%A8%E5%85%B5%EF%BC%89%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.2.</span> <span class="nav-text">Sentinel（哨兵）模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86-1"><span class="nav-number">1.2.1.</span> <span class="nav-text">1. 基本原理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-%E9%83%A8%E7%BD%B2%E6%BC%94%E7%A4%BA"><span class="nav-number">1.2.2.</span> <span class="nav-text">2. 部署演示</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-%E5%93%A8%E5%85%B5%E6%A8%A1%E5%BC%8F%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9"><span class="nav-number">1.2.3.</span> <span class="nav-text">3. 哨兵模式的优缺点</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Cluster%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.3.</span> <span class="nav-text">Cluster模式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86-2"><span class="nav-number">1.3.1.</span> <span class="nav-text">1. 基本原理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-%E9%83%A8%E7%BD%B2%E6%BC%94%E7%A4%BA-1"><span class="nav-number">1.3.2.</span> <span class="nav-text">2. 部署演示</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-Cluster%E6%A8%A1%E5%BC%8F%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9"><span class="nav-number">1.3.3.</span> <span class="nav-text">3. Cluster模式的优缺点</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%80%BB%E7%BB%93"><span class="nav-number">1.4.</span> <span class="nav-text">总结</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->
    
           <div>
            <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="//music.163.com/outchain/player?type=2&id=144301&auto=1&height=66"></iframe>
           </div>
   
      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">林壮荣</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/blog/archives/">
        
          <span class="site-state-item-count">20</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/blog/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/blog/tags/">
        <span class="site-state-item-count">3</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">林壮荣</span>
</div>
<div class="theme-info">
  <div class="powered-by"></div>
  <span class="post-count">博客全站共31.2k字</span>
</div>

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

<div class="powered-by">
  <i class="fa fa-user-md"></i>
  <span id="busuanzi_container_site_pv">
    本站访问量:<span id="busuanzi_value_site_pv"></span>次
  </span>
  <span class="post-meta-divider">|</span>
  <span id="busuanzi_container_site_uv">
    本站总访客量：<span id="busuanzi_value_site_uv"></span>人
  </span>
</div>

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/blog/lib/anime.min.js"></script>
  <script src="/blog/lib/velocity/velocity.min.js"></script>
  <script src="/blog/lib/velocity/velocity.ui.min.js"></script>

<script src="/blog/js/utils.js"></script>

<script src="/blog/js/motion.js"></script>


<script src="/blog/js/schemes/pisces.js"></script>


<script src="/blog/js/next-boot.js"></script>




  




  
<script src="/blog/js/local-search.js"></script>













  

  

</body>
</html>
